package com.gitee.apanlh.util.valid;

import com.gitee.apanlh.util.base.ArrayUtils;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.util.reflection.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 *	参数验证工具类
 *
 *	@author Pan
 */
public class ValidParam {

	/**
	 * 	构造函数
	 *
	 * 	@author Pan
	 */
	private ValidParam() {
		//	不允许外部实例
		super();
	}

	/**
	 * 	验证特定一个或者多个参数其中有一个参数为null或空直接返回false
	 * 	<br>如果要使用其他类型  则转换成String
	 * 	<br>true为存在值  false为空
	 *
	 * 	@author Pan
	 * 	@param  params	参数
	 * 	@return boolean
	 */
	public static boolean required(String... params) {
		if (isEmpty(params)) {
			return false;
		}

		for (String param : params) {
            if (isEmpty(param)) {
                return false;
            }
        }
		return true;
	}

	/**
	 * 	验证是否为空或者值为0
	 *
	 * 	@author Pan
	 * 	@param 	params	参数
	 * 	@return	boolean
	 */
	public static boolean requiredAndNotZero(String... params) {
		if (isEmpty(params)) {
			return false;
		}

		for (String param : params) {
            if (isEmpty(param) || "0".equals(param)) {
                return false;
            }
        }
		return true;
	}

	/**
	 * 	验证是否字符串包含全角字符或者空格
	 * 	<br>true为存在值  false为空
	 *
	 * 	@author Pan
	 * 	@param  params	参数
	 * 	@return boolean
	 */
	public static boolean requiredContainsSpace(String... params) {
		if (isEmpty(params)) {
			return false;
		}

		for (String param : params) {
			if (isEmpty(param) || isContainsSpace(param)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 	验证Map所有Value的值 不可为空
	 * 	<br>true为存在值  false为空
	 *
	 * 	@author Pan
	 *  @param  <K>     	键类型
	 *  @param  <V>     	值类型
	 * 	@param  paramMap	map参数
	 * 	@return boolean
	 */
	public static <K, V> boolean requiredMapByValue(Map<K, V> paramMap) {
		if (MapUtils.isEmpty(paramMap)) {
			return false;
		}

		Iterator<Map.Entry<K, V>> entryIterator = IteratorUtils.entrySet(paramMap);
		while (entryIterator.hasNext()) {
			Map.Entry<K, V> next = entryIterator.next();
			V value = next.getValue();
			if (value == null || (value instanceof String && isEmpty((String) value))) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 	验证对象属性是否全部存在值 如果一个不存在则判定为空
	 * 	<br>true为存在值  false为空
	 *
	 * 	@author Pan
	 *  @param  <T>     数据类型
	 * 	@param  obj		对象
	 * 	@return	boolean
	 */
	public static <T> boolean requiredBean(T obj) {
		if (null == obj) {
			return false;
		}

		Field[] fields = ReflectionUtils.getFields(obj, true);
		if (ArrayUtils.isEmpty(fields)) {
			return false;
		}

		for(int i = 0; i < fields.length; i++) {
			if (null == ReflectionUtils.getFieldValue(obj, fields[i].getName())) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 	是否为Null
	 *
	 * 	@author Pan
	 *  @param  <T>     数据类型
	 * 	@param 	t		对象
	 * 	@return	boolean
	 */
	public static <T> boolean isNull(T t) {
		return t == null;
	}

	/**
	 * 	全部参数是否为Null
	 * 	<br>任意一个非Null返回false
	 *
	 * 	@author Pan
	 *  @param  <T>     数据类型
	 * 	@param 	t		对象
	 * 	@return	boolean
	 */
	@SafeVarargs
	public static <T> boolean isNull(T... t) {
		if (t == null) {
			return true;
		}

		for (int i = 0; i < t.length; i++) {
			if (null != t[i]) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 	是否不为Null
	 *
	 * 	@author Pan
	 *  @param  <T>     数据类型
	 * 	@param 	t		对象
	 * 	@return	boolean
	 */
	public static <T> boolean isNotNull(T t) {
		return null != t;
	}

	/**
	 * 	全部参数必须为非Null
	 * 	<br>任意一个Null返回false
	 *
	 * 	@author Pan
	 *  @param  <T>     数据类型
	 * 	@param 	t		对象
	 * 	@return	boolean
	 */
	@SafeVarargs
	public static <T> boolean isNotNull(T... t) {
		if (t == null) {
			return false;
		}

		for (int i = 0; i < t.length; i++) {
			if (null == t[i]) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 	字符串是否为空
	 *
	 * 	@author Pan
	 * 	@param  param	字符串
	 * 	@return	boolean
	 */
	public static boolean isEmpty(String param) {
		return StringUtils.isEmpty(param);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(String[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(byte[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(short[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(int[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(long[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(float[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(double[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(boolean[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	包装类型数组是否为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isEmpty(char[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	包装类型数组是否为空
	 *
	 * 	@author Pan
	 *  @param  <T>      数据类型
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static <T> boolean isEmpty(T[] arr) {
		return ArrayUtils.isEmpty(arr);
	}

	/**
	 * 	Collection是否为空
	 *
	 * 	@author Pan
	 *  @param  <E>      数据类型
	 * 	@param  param	集合
	 * 	@return	boolean
	 */
	public static <E> boolean isEmpty(Collection<E> param) {
		return CollUtils.isEmpty(param);
	}

	/**
	 * 	Map是否为空
	 *
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param  map		Map
	 * 	@return	boolean
	 */
	public static <K, V> boolean isEmpty(Map<K, V> map) {
		return MapUtils.isEmpty(map);
	}

	/**
	 *	Set是否为空
	 *
	 * 	@author Pan
	 *	 @param <E> 	数据类型
	 * 	@param  set		Set对象
	 * 	@return	boolean
	 */
	public static <E> boolean isEmpty(Set<E> set) {
	   return CollUtils.isEmpty(set);
	}

	/**
	 * 	字符串是否不为空
	 *
	 * 	@author Pan
	 * 	@param  param	字符串
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(String param) {
		return !isEmpty(param);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(String[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(byte[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(short[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(int[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(long[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(float[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(double[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(boolean[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	包装类型数组是否不为空
	 *
	 * 	@author Pan
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static boolean isNotEmpty(char[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	包装类型数组是否不为空
	 *
	 * 	@author Pan
	 *  @param  <T>      数据类型
	 * 	@param  arr		数组
	 * 	@return	boolean
	 */
	public static <T> boolean isNotEmpty(T[] arr) {
		return !isEmpty(arr);
	}

	/**
	 * 	Collection是否不为空
	 *
	 * 	@author Pan
	 *  @param  <E>      数据类型
	 * 	@param  param	集合
	 * 	@return	boolean
	 */
	public static <E> boolean isNotEmpty(Collection<E> param) {
		return !isEmpty(param);
	}

	/**
	 * 	Map是否不为空
	 *
	 * 	@author Pan
	 *  @param  <K>     键类型
	 *  @param  <V>     值类型
	 * 	@param  map		Map
	 * 	@return	boolean
	 */
	public static <K, V> boolean isNotEmpty(Map<K, V> map) {
		return !isEmpty(map);
	}

	/**
	 *	Set是否不为空
	 *
	 * 	@author Pan
	 * 	@param 	<E>		数据类型
	 * 	@param  set		Set对象
	 * 	@return	boolean
	 */
	public static <E> boolean isNotEmpty(Set<E> set) {
		return !isEmpty(set);
	}

	/**
	 * 	判断对象的属性值是否为空或者对象为null(任意一个属性存即不为空)
	 * 	<br>用于判断new的对象或null对象
	 * 	<br>返回true为空
	 *
	 * 	@author Pan
	 *  @param  <T>     数据类型
	 * 	@param  obj		对象
	 * 	@return	boolean
	 */
	public static <T> boolean isEmptyBean(T obj) {
	   return null == obj || isEmpty(ClassConvertUtils.toMap(obj));
	}

	/**
	 * 	字符串是否为全数字
	 *
	 * 	@author Pan
	 * 	@param 	str		字符串
	 * 	@return boolean
	 */
	public static boolean isNumber(String str) {
		if (isEmpty(str)) {
			return false;
		}
		for (int i = 0; i < str.length(); i++) {
			char c = str.charAt(i);
			if (!isNumber(c)) {
				if (i == 0 && '-' == c) {
					continue;
				}
				return false;
			}
		}
		return true;
	}

	/**
	 * 	ASCII-数字
	 *
	 *	@author Pan
	 * 	@param 	c 字符
	 * 	@return	boolean
	 */
	public static boolean isNumber(char c) {
		return c >= 48 && c <= 57;
	}

	/**
	 * 	验证一个字符是否为a-zA-Z的字母
	 *
	 *	@author Pan
	 * 	@param 	c 字符
	 * 	@return	boolean
	 */
	public static boolean isLetter(char c) {
		return isUpperCaseLetter(c) || isLowerCaseLetter(c);
	}

	/**
	 * 	验证一个字符是否为大写字母 A 到 Z 之间的字符
	 *
	 *	@author Pan
	 * 	@param 	c 字符
	 * 	@return	boolean
	 */
	public static boolean isUpperCaseLetter(char c) {
		return c >= 'A' && c <= 'Z';
	}

	/**
	 * 	验证一个字符是否为小写字母a到z之间的字符
	 *
	 *	@author Pan
	 * 	@param 	c 字符
	 * 	@return	boolean
	 */
	public static boolean isLowerCaseLetter(char c) {
		return c >= 'a' && c <= 'z';
	}

	/**
	 * 	判断是否字符串是否包含空格或全角空格
	 * 	<br>true为存在空格或全角空格
	 *
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return	boolean
	 */
	public static boolean isContainsSpace(String str) {
		if (str == null) {
			return false;
		}

		for (int i = 0, len = str.length(); i < len; i++) {
			if (isContainsSpace(str.charAt(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 	判断是否字符串是否包含空格或全角空格
	 *
	 * 	@author Pan
	 * 	@param  chars	字符数组
	 * 	@return	boolean
	 */
	public static boolean isContainsSpace(char[] chars) {
		for (int i = 0, len = chars.length; i < len; i++) {
			if (isContainsSpace(chars[i])) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 	判断char是否包含空格或全角空格
	 * 	<br>true为存在空格或全角空格
	 *
	 * 	@author Pan
	 * 	@param  c	字符
	 * 	@return boolean
	 */
	public static boolean isContainsSpace(char c) {
		return c == ' ' || c == '\u3000';
	}

	/**
	 *  判断包含全角符号
	 * 	<br>true为存在空格或全角空格
	 *
	 * 	@author Pan
	 * 	@param  str		字符串
	 * 	@return boolean
	 */
	public static boolean isFullWidthCharacter(String str) {
		if (str == null) {
			return false;
		}

		for (int i = 0, cLen = str.length(); i < cLen; i++) {
			if (isFullWidthCharacter(str.charAt(i))) {
				return true;
			}
		}
		return false;
	}

	/**
	 *  判断包含全角符号
	 * 	<br>true为存在空格或全角空格
	 *
	 * 	@author Pan
	 * 	@param  c		字符
	 * 	@return boolean
	 */
	public static boolean isFullWidthCharacter(char c) {
		//	最小以及最大的全角字符
		int minCase = 65281;
		int maxCase = 65374;
		int moneyCase = 65509;
		return (c >= minCase && c <= maxCase) || c == moneyCase;
	}
}
